package com.btl.component.crypto.endpoint;


import com.btl.boot.core.util.JsonUtils;
import com.btl.component.crypto.annotation.Decrypt;
import com.btl.component.crypto.constant.SecVersionEnum;
import com.btl.component.crypto.dto.CryptoDto;
import com.btl.component.crypto.dto.CryptoHeader;
import com.btl.component.crypto.util.AesCryptoUtil;
import com.btl.component.crypto.util.RsaCryptoUtil;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import java.util.Map;

@Tag(name = "参数解密")
@Slf4j
@RestController
@RequestMapping("crypto")
public class CryptoController {

    /**
     * 请求参数加密
     */
    @PostMapping("e-q")
    public CryptoDto eq(@RequestBody @Valid Map<String, Object> request) throws Exception {
        SecVersionEnum version = SecVersionEnum.V1;
        String key = AesCryptoUtil.generateKey();
        String payloads = JsonUtils.toJsonString(request);
        assert payloads != null;
        String encrypt = AesCryptoUtil.encrypt(payloads, key);
        String keyEn = RsaCryptoUtil.encrypt(version.getServerName(), version.getServerKeyStorePath(), version.getServerKeyStorePassword(), key);
        CryptoDto cryptoDto = new CryptoDto();
        CryptoHeader cryptoHeader = new CryptoHeader();
        cryptoHeader.setKey(keyEn);
        cryptoHeader.setVersion(version.getClientName());
        cryptoHeader.setTimestamp(System.currentTimeMillis());
        cryptoDto.setHeader(cryptoHeader);
        String header = JsonUtils.toJsonString(cryptoHeader);
        cryptoDto.setPayload(encrypt);
        String sign = RsaCryptoUtil.sign(version.getClientName(), version.getClientKeyStorePath(), version.getClientKeyStorePassword(), header + encrypt);
        cryptoDto.setSignature(sign);
        return cryptoDto;
    }

    /**
     * 请求参数解密
     */
    @PostMapping("d-q")
    @Decrypt
    public Map<String, Object> dq(@RequestBody @Valid Map<String, Object> request) {
        return request;
    }


    /**
     * 返回参数解密
     */
    @PostMapping("d-r")
    public JsonNode dr(@RequestBody @Valid CryptoDto cryptoDto) throws Exception {
        SecVersionEnum version = SecVersionEnum.valueOf(cryptoDto.getHeader()
                .getVersion());
        CryptoHeader header = cryptoDto.getHeader();
        String jsonString = JsonUtils.toJsonString(header);
        boolean verify = RsaCryptoUtil.verify(version.getServerName(), version.getServerKeyStorePath(), version.getServerKeyStorePassword(), jsonString + cryptoDto.getPayload(), cryptoDto.getSignature());
        if (!verify) {
            throw new Exception("签名异常");
        }
        String keyDec = RsaCryptoUtil.decrypt(version.getClientName(), version.getClientKeyStorePath(), version.getClientKeyStorePassword(), cryptoDto.getHeader()
                .getKey());
        String decrypt = AesCryptoUtil.decrypt(cryptoDto.getPayload(), keyDec);
        return JsonUtils.readTree(decrypt);
    }
}
